package com.yb.xczx.cloud.auth.provider;

import com.yb.core.constant.RedisKeyConstant;
import com.yb.core.enums.LoginTypeEnum;
import com.yb.xczx.cache.manager.api.XczxStringCacheManager;
import com.yb.xczx.cloud.auth.bean.XczxAbstractAuthenticationToken;
import com.yb.xczx.cloud.auth.bean.XczxSysUser;
import com.yb.xczx.cloud.auth.bean.XczxUserLoginCodeAuthenticationToken;
import com.yb.xczx.cloud.auth.bean.XczxUserPassAuthenticationToken;
import com.yb.xczx.cloud.auth.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.StringUtils;

/**
 * Copyright (C), 2022-2023, 姚兵
 * Author: 32210
 * Date: 2023/5/17 21:02
 * FileName: XczxTokenAuthenticationProvider
 * Description:
 */
@Slf4j
public class XczxUserLoginCodeAuthenticationProvider extends XczxAbstractUserDetailsAuthenticationProvider {

    @Autowired
    XczxStringCacheManager xczxStringCacheManager;
    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, XczxAbstractAuthenticationToken authentication) throws AuthenticationException {
        XczxUserLoginCodeAuthenticationToken authenticationToken= (XczxUserLoginCodeAuthenticationToken) authentication;
        String loginCode = authenticationToken.getLoginCode();
        String username = userDetails.getUsername();
        String remoteCode = xczxStringCacheManager.getString(String.format(RedisKeyConstant.LOGIN_USER_LOGINCODE_KEY, username));

        if(!StringUtils.hasText(remoteCode)){
            log.info("remoteCode is not present");
            throw new BadCredentialsException("code已失效");
        }
        if(!loginCode.equals(remoteCode)){
            log.info("logincode 和 remotecode 不一致");
            throw new BadCredentialsException("code错误");
        }

        xczxStringCacheManager.delete(String.format(RedisKeyConstant.LOGIN_USER_LOGINCODE_KEY,username));
    }

    @Override
    protected UserDetails retrieveUser(String username, XczxAbstractAuthenticationToken authentication) throws AuthenticationException {

        UserDetails userDetails = this.sysUserService.loadUserByUsername(username);

        return userDetails;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return XczxUserLoginCodeAuthenticationToken.class.isAssignableFrom(authentication);
    }

    @Override
    protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) {
        XczxUserLoginCodeAuthenticationToken loginCodeAuthenticationToken= (XczxUserLoginCodeAuthenticationToken) authentication;
        XczxUserLoginCodeAuthenticationToken result = XczxUserLoginCodeAuthenticationToken.authenticated((XczxSysUser) user,loginCodeAuthenticationToken.getLoginCode(),"",this.authoritiesMapper.mapAuthorities(user.getAuthorities()));
        result.setDetails(authentication.getDetails());
        ((XczxSysUser) user).setLoginType(LoginTypeEnum.LOGIN_CODE.getLoginType());
        this.logger.debug("Authenticated user");
        return result;
    }
}
